<?php
/**
 * Function:
 * Description:
 * Abo 2019/3/19 23:57
 * Email: abo2013@foxmail.com
 */

namespace Abo\Smartsync\Logic;


use Abo\Smartsync\Repositories\SyncRepository;
use Abo\Smartsync\Interfaces\SmartSyncBusinessClientInterface;

class SyncDataIntoTableLogic
{
    public $updateBatch, $SyncRepository;
    public $tableName,$BusinessClient;

    public function __construct( string $tableName = '', $BusinessClient = null )
    {
        if ( !$tableName ) {
            throw new \Exception( '未设置表名' );
        }
        if ( !($BusinessClient instanceof SmartSyncBusinessClientInterface) ) {
            throw new \Exception( '同步数据业务类 未继承 SmartSyncBusinessClientInterface' );
        }

        $this->tableName = $tableName;
        $this->BusinessClient = $BusinessClient;        // 用户 业务逻辑类

        $this->SyncRepository = new SyncRepository( $tableName );   // 包内 数据操作类
        $this->updateBatch = $this->SyncRepository->updateBatchInstance();
        $this->SyncRepository->setSyncTimePeriod( $BusinessClient->syncTimePeriod() ); // 同步数据范围
    }

    /**
     * 功能字段
     * md5_new 更新数组生成 新MD5 32
     * md5_origin 原MD5 32
     * update_batch 更新批次
     * remove_at 移除时间
     *
     * 流程:
     * 1 生成更新批次标识 update_batch
     * 2 忠诚同步数据
     * 3 把 新增 同步数据 更新到 我方逻辑表 (remove_time = 0 && update_batch = 当前更新标识 && md5_origin = '' && md5_new != '')
     * 4 把 变更 同步数据 按条件更新到 我方逻辑表 (remove_time = 0 && update_batch = 当前更新标识 && md5_origin != '' && md5_new != md5_origin)
     * 5 把 失联 同步数据 按条件更新到 我方逻辑表 (remove_time = 0 && update_batch != 当前更新标识 && md5_origin != '' && md5_new = '')
     * 6 本更新批次,收尾标记
     * 6.1 变动的 md5_origin = md5_new
     * 6.2 失联的 remove_time = time()
     * 6.3 全部 md5_new = ''
     *
     * @param array $syncData
     * @return bool
     * @throws \Exception
     */
    public function syncDataIntoTable( array $syncData = [] )
    {
        if ( !$syncData ) { return false;  }
        $this->insertSyncData2DB( $syncData ); // 第一步:忠诚同步数据到数据库

        $this->syncData2BusinessLogic( $this->BusinessClient );

        $this->updateMd5Origin(); // 本更新批次,收尾标记

    }

    /** 2 忠诚同步数据 */
    protected function insertSyncData2DB( array $syncData = [] )
    {
        if ( !$syncData ) { return false;  }

        $chunkArr = array_chunk($syncData, 500);
        foreach ($chunkArr as $v2Arr) {
            foreach ( $v2Arr as $v2Insert ) {
                $temData2Insert = $v2Insert;
                $temData2Insert [ 'update_batch' ] = $this->updateBatch;
                // $temData2Insert [ 'md5_origin' ] = '';
                $temData2Insert [ 'md5_new' ] = md5( implode('_', $v2Insert ) );
                $temData2Insert [ 'remove_time' ] = 0;

                $this->SyncRepository->duplicateKeyInsert( $temData2Insert, $this->tableName );
            }
        }
    }

    /** 3 按逻辑 更新 变更数据 到 业务表 @throws \Exception*/
    public function syncData2BusinessLogic( SmartSyncBusinessClientInterface $BusinessClient )
    {
        // 重写业务代码
        $insertSyncList = $this->SyncRepository->getInsertSyncList();
        $ret2Insert = $BusinessClient->handleInsertSyncList( $insertSyncList );

        $updateSyncList = $this->SyncRepository->getUpdateSyncList();
        $ret2Update = $BusinessClient->handleUpdateSyncList( $updateSyncList );

        $unsetSyncList = $this->SyncRepository->getUnsetSyncList();
        $ret2Unset = $BusinessClient->handleUnsetSyncList( $unsetSyncList );

        return [ $ret2Insert, $ret2Update, $ret2Unset ];
    }

    /**
     * 6 本更新批次,收尾标记
     * 6.1 变动的 md5_origin = md5_new
     * 6.2 失联的 remove_time = time()
     * 6.3 全部 md5_new = ''
     */
    protected function updateMd5Origin()
    {
        // 新增,变更的复位
        $sql2Str = "UPDATE {$this->tableName} SET md5_origin = md5_new WHERE md5_new <> '' AND update_batch = '{$this->updateBatch}'";
        \DB::update( $sql2Str );
        // 失联
        $sql2Str = "UPDATE {$this->tableName} SET remove_time = ".time()." WHERE md5_new != md5_origin AND md5_new = '' AND update_batch = '{$this->updateBatch}'";
        \DB::update( $sql2Str );

        $sql2Str = "UPDATE {$this->tableName} SET md5_new = ''";
        \DB::update( $sql2Str );
    }
}